from . import news_blue
from flask import render_template, session, abort, g,request,jsonify
from info.models import User, News,Comment,CommentLike
import logging
from info import constants, db
from info.utils.comment import user_login_data
from info.utils import response_code


@news_blue.route('/comment_like',methods=['POST'])
@user_login_data
def comment_like():
    """新闻点赞
    1.判断用户是否登录
    2.接受参数：comment_id, action
    3.校验参数：判断参数是否齐全，判断action是否在范围内（add, remove）
    4.查询要被点赞的评论是否存在，只有存在才能点赞
    5.根据action的值，实现点赞或者取消点赞
    6.将数据同步到数据库
    7.返回收藏或者取消收藏的结果
    """
    # 1.判断用户是否登录
    user = g.user
    if not user:
        return jsonify(errno=response_code.RET.SESSIONERR, errmsg='用户未登录')

    # 2.接受参数：comment_id, action
    json_dict = request.json
    comment_id = json_dict.get('comment_id')
    action = json_dict.get('action')

    # 3.校验参数：判断参数是否齐全，判断action是否在范围内（add, remove）
    if not all([comment_id, action]):
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='缺少参数')
    if action not in ['add', 'remove']:
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='参数错误')

    # 4.查询要被点赞的评论是否存在，只有存在才能点赞
    try:
        comment = Comment.query.get(comment_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=response_code.RET.DBERR, errmsg='查询评论数据失败')
    if not comment:
        return jsonify(errno=response_code.RET.NODATA, errmsg='评论信息不存在')

    # 5.根据action的值，实现点赞或者取消点赞
    # 需要查询并判断，点赞的记录是否存在
    comment_like_model = CommentLike.query.filter(CommentLike.comment_id == comment_id,
                                                  CommentLike.user_id == user.id).first()
    if action == 'add':
        # 点赞
        if not comment_like_model:
            # 新建记录表示点赞
            comment_like_model = CommentLike()
            comment_like_model.user_id = user.id
            comment_like_model.comment_id = comment_id

            # 需要给评论追加点赞数
            comment.like_count += 1
            # 同步到数据库
            db.session.add(comment_like_model)
    else:
        # 取消点赞
        if comment_like_model:
            # 需要给评论减少点赞数
            comment.like_count -= 1
            # 同步数据库
            db.session.delete(comment_like_model)

    # 6.将数据同步到数据库
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=response_code.RET.DATAERR, errmsg='操作失败')

    # 7.返回收藏或者取消收藏的结果
    return jsonify(errno=response_code.RET.OK, errmsg='操作成功')


@news_blue.route('/news_comment', methods=['POST'])
@user_login_data
def news_comment():
    """新闻评论
    1.判断用户是否登录
    2.接受参数：news_id, comment, parent_id
    3.校验参数：判断参数是否齐全，判断news_id和parent_id是否是整数
    4.判断要评论的新闻是否存在，只有存在才能评论
    5.根据参数，创建Comment模型类的对象，并给属性赋值
    6.同步数据到数据库
    7.响应评论的结果,记得将评论数据返回给前端，方便前端展示评论后内容
    """
    # 1.判断用户是否登录
    user = g.user
    if not user:
        return jsonify(errno=response_code.RET.SESSIONERR, errmsg='用户未登录')

    # 2.接受参数：news_id, comment, parent_id
    json_dict = request.json
    news_id = json_dict.get('news_id')
    comment_content = json_dict.get('comment')
    parent_id = json_dict.get('parent_id')

    # 3.校验参数：判断参数是否齐全，判断news_id和parent_id是否是整数
    if not all([news_id, comment_content]): # parent_id:如果是直接评论的新闻，可以不传
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='缺少必传参数')
    try:
        news_id = int(news_id)
        if parent_id:
            parent_id = int(parent_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='参数错误')

    # 4.判断要评论的新闻是否存在，只有存在才能评论
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=response_code.RET.DBERR, errmsg='查询新闻数据失败')
    if not news:
        return jsonify(errno=response_code.RET.NODATA, errmsg='新闻不存在')

    # 5.根据参数，创建Comment模型类的对象，并给属性赋值(核心点)
    comment = Comment()
    comment.user_id = user.id
    comment.news_id = news_id
    comment.content = comment_content
    # 如果没有传入parent_id,表示直接评论的新闻；如归传入了parent_id表示是回复评论
    if parent_id:
        comment.parent_id = parent_id

    # 6.同步数据到数据库
    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=response_code.RET.DBERR, errmsg='存储评论数据失败')

    # 7.响应评论的结果,记得将评论数据返回给前端，方便前端展示评论后内容
    return jsonify(errno=response_code.RET.OK, errmsg='OK', data=comment.to_dict())


@news_blue.route('/news_collect', methods=['POST'])
@user_login_data
def news_collect():
    """新闻收藏：只有登录用户才能收藏新闻
    1.判断用户是否登录
    2.接受参数：news_id,action
    3.校验参数：判断参数是否齐全，判断action是否在指定的范围
    4.判断新闻数据是否存在，只有存在的新闻才能收藏
    5.根据action的值，实现收藏或者取消收藏
    6.将数据同步到数据库
    7.返回收藏或者取消收藏的结果
    """

    # 1.判断用户是否登录
    user = g.user
    if not user:
        return jsonify(errno=response_code.RET.SERVERERR,errmsg='用户未登录')

    # 2.接受参数：comment_id, action
    json_dict = request.json
    news_id = json_dict.get('news_id')
    action = json_dict.get('action')

    # 3.校验参数：判断参数是否齐全，判断action是否在范围内（add, remove）
    if not all([news_id,action]):
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='缺少参数')
    if action not in ['collect', 'cancel_collect']:
        return jsonify(errno=response_code.RET.PARAMERR, errmsg='参数错误')

    # 4.判断新闻数据是否存在，只有存在的新闻才能收藏
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=response_code.RET.DBERR, errmsg='查询新闻数据失败')
    if not news:
        return jsonify(errno=response_code.RET.NODATA, errmsg='新闻不存在')

    # 5.根据action的值，实现收藏或者取消收藏（核心点）
    if action =='action':
        #收藏
        if news not in user.collection_news:
        # 如果当前的新闻没有被收藏，就把当前的新闻添加到当前登录用户的收藏列表中
            user.collection_news.append(news)
    else:
        # 取消收藏
        if news in user.collection_news:
            user.collection_news.remove(news)

    # 6.将数据同步到数据库
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=response_code.RET.DBERR, errmsg="操作失败")

    # 7.返回收藏或者取消收藏的结果
    return jsonify(errno=response_code.RET.OK, errmsg='操作成功')

@news_blue.route('/detail/<int:news_id>')
@user_login_data
def news_detail(news_id):
    """
    新闻详情
    :param news_id: 新闻id
    :return: 新闻详情
    1.查询用户基本信息
    2.查询点击排行信息
    3.查询新闻详情信息
    4.需要判断当前登录用户是否收藏过该新闻
    5.查询出新闻的评论信息并展示
    6.查询当前登录用户对哪些评论点赞了
    """
    # 1.查询用户基本信息
    # 从g变量中读取user
    user = g.user

    # 2.查询点击排行信息
    news_clicks = None
    try:
        news_clicks = News.query.order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS)
    except Exception as e:
        logging.error(e)

    # 3.查询新闻详情信息
    news = None
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
    if not news:
        # 现在抛出404，将来捕获404，然后对所有的404进行统一的处理
        abort(404)

    # 更新新闻的点击量
    news.clicks += 1
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()

    # 4.需要判断当前登录用户是否收藏过该新闻
    is_collected = False
    # if 当前登录用户收藏了该新闻:
    if user:
        if news in user.collection_news:
            is_collected = True

    # 5.查询出新闻的评论信息并展示
    comments = None # comments = [Comment, Comment, Comment, ...]
    try:
        comments = Comment.query.filter(Comment.news_id==news_id).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        logging.error(e)

    # 6.查询当前登录用户对哪些评论点赞了(难点)
    comment_like_ids = []
    if user:
        try:
            comment_likes = CommentLike.query.filter(CommentLike.user_id == user.id).all()
            comment_like_ids = [comment_like.comment_id for comment_like in comment_likes]
        except Exception as e:
            logging.error(e)

    comment_dict_list = []
    for comment in comments:
        # 先转字典
        comment_dict = comment.to_dict()
        comment_dict['is_like'] = False
        if comment.id in comment_like_ids:
            # 表示该条评论被该用户点赞了，将is_like设置为True
            comment_dict['is_like'] = True

        comment_dict_list.append(comment_dict)

    # 构造渲染详情页的上下文
    context = {
        'user':user.to_dict() if user else None,
        'news_clicks':news_clicks,
        'news':news.to_dict(),
        'is_collected':is_collected,
        'comments':comment_dict_list
    }

    return render_template('news/detail.html', context=context)